﻿/*
 *	Copyright (c) 2009 Queensland University of Technology. All rights reserved.
 *	The QUT Bioinformatics Collection is open source software released under the 
 *	Microsoft Public License (Ms-PL): http://www.microsoft.com/opensource/licenses.mspx.
 */
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using NCBI_Eutils.Eutils;
using System.Windows.Threading;
using System.Threading;
using QUT.Bio.Util;
using System.Windows;
using BlastExplorer.SilverMapDataProducer;
using QUT.Bio.SilverMap.ObjectModel;

namespace BlastExplorer {
	public class EUtil {
	
		/// <summary>
		/// The databases known to be supported.
		/// TODO: make comprehensive.
		/// </summary>

		public enum Database { protein, nucleotide };
	
		/// <summary>
		/// NCBI eUtil web service proxy.
		/// </summary>
	
		eUtilsService eServ = new eUtilsService();

		/// <summary>
		/// A lookup table associating a gi number with its corresponding genbank record.
		/// </summary>

		private static Dictionary<string, GBSeqType> genbankCache = new Dictionary<string, GBSeqType>();

		/// <summary>
		/// Executes an entrez query on the specified database.
		/// </summary>
		/// <param name="database"></param>
		/// <param name="giNumbers"></param>
		/// <param name="onSuccess"></param>
		/// <param name="onFailure"></param>
		
		public void EntrezQuery (
			Database database,
			IEnumerable<string> giNumbers,
			Action<Dictionary<string, GBSeqType>> onSuccess,
			Action onFailure
		) {
			new Thread( delegate() {
				try {
					Dictionary<string, GBSeqType> results = new Dictionary<string,GBSeqType>();
					List<string> detailsUnknown = new List<string>();
					
					foreach ( string giNumber in giNumbers ) {
						if ( genbankCache.ContainsKey( giNumber ) ) {
							results[giNumber] = genbankCache[giNumber];
						}
						else {
							detailsUnknown.Add( giNumber );
						}
					}
					
					if ( detailsUnknown.Count > 0 ) {
						eFetchResultType searchResult = eServ.run_eFetch_MS( database.ToString(), detailsUnknown.Join( "," ), "", "", "", "", "", "", "", "", "", "", "", "" );
						
						if ( searchResult != null && searchResult.GBSet != null ) {
							foreach ( GBSeqType gbSeq in searchResult.GBSet ) {
								string giNumber = GetGI(gbSeq);
								genbankCache[ giNumber ] = gbSeq;
								results[ giNumber ] = gbSeq;
							}
						}
					}
					
					Application.Current.Dispatcher.BeginInvoke( onSuccess, results );
				}
				catch ( Exception e ) {
					Debug.WriteLine( String.Format( "Exception {0}", e ) );
					Application.Current.Dispatcher.BeginInvoke( onFailure );
				}
			} ).Start();
		}

		public static string GetGI ( GBSeqType gbSeq ) {
			foreach ( var q in gbSeq.GBSeq_otherseqids ) {
				if ( q.StartsWith( "gi|" ) ) {
					return q.Substring( 3 );
				}
			}

			return string.Empty;
		}
	}
}
